#include <string.h>
#include <unistd.h>

#include "svuv.hpp"
#include "svfifo.hpp"
#include "svcp.hpp"
#include "svdebug.hpp"

#define TEST_SVUV           0
#define TEST_SVFIFO         1
#define TEST_SVCP           2
#define TEST_SVDEBUG        3


#define TEST_MODULE         TEST_SVDEBUG


#if (TEST_MODULE == TEST_SVUV)
#define TCP_TEST_SIZE        (100 * 1024 * 1024)

#define TEST_SERVER_M1_IP          "192.168.148.50"
#define TEST_SERVER_M1_PORT        33331
#define TEST_SERVER_M2_IP          "192.168.148.50"
#define TEST_SERVER_M2_PORT        33332

#define TEST_CLIENT1_IP          "192.168.148.237"
#define TEST_CLIENT1_PORT        65531

#define TEST_CLIENT2_IP          "192.168.148.237"
#define TEST_CLIENT2_PORT        65532

/*******************************************************TCP client***************************************************************************************/
static void client1SendFunc(void *arg)
{
    class svuv *svUv = (class svuv *)arg;
    uint8_t *data = new uint8_t [TCP_TEST_SIZE];
    uint8_t i = 0;

    data[0] = 0xD2;
    data[1] = 0x8C;
    data[2] = 0x02;
    data[3] = 0x00;
    data[4] = 0xFF;
    data[5] = 0xFF;
    data[6] = 0xFF;
    data[7] = 0xFF;
    data[8] = 0xFF;
    data[9] = 0xFF;
    data[10] = 0xFF;
    data[11] = 0x00;
    data[12] = 0x05;
    data[13] = 0x00;
    data[14] = 0x00;
    data[15] = 0x02;
    data[16] = 0xAA;
    data[17] = 0xbb;
    data[18] = 0xcc;
    data[19] = 0xcc;

    while (1)
    {
        // memset(data, i, TCP_TEST_SIZE);
        // fprintf(stdout, "client1SendFunc\n");
        svUv->gTcpClientSend(TEST_CLIENT1_IP, TEST_CLIENT1_PORT, data, 20);
        i++;
        delayMs(100);
        // sleep(1);
    }
}

static void client1RecvFunc(void *arg)
{
    class svuv *svUv = (class svuv *)arg;
    uint8_t *buff = new uint8_t [128 * 1024];
    int32_t ret = 0;
    int32_t allLen = 0;
    unsigned long long now = 0;

    while (1)
    {
        memset(buff, 0x00, 128 * 1024);

        ret = svUv->gTcpClientRecv(TEST_CLIENT1_IP, TEST_CLIENT1_PORT, buff, 128 * 1024);
        if (ret > 0)
        {
            allLen += ret;
            // if (allLen >= TCP_TEST_SIZE)
            {
                fprintf(stdout, "client1RecvFunc\n");
                fprintf(stdout, "recv %d , data %02x %02x\n", ret, buff[0], buff[1]);
                allLen = 0;
            }
        }
        // sysGetCurPts(&now);
        // printf("usleep time = %lld\n", now);

        // usleep(1000);
        delayMs(1);
    }
}

static void client2SendFunc(void *arg)
{
    class svuv *svUv = (class svuv *)arg;
    uint8_t *data = new uint8_t [TCP_TEST_SIZE];
    uint8_t i = 0;

    data[0] = 0x4D;
    data[1] = 0x73;
    data[2] = 0x02;
    data[3] = 0x00;
    data[4] = 0xFF;
    data[5] = 0xFF;
    data[6] = 0xFF;
    data[7] = 0xFF;
    data[8] = 0xFF;
    data[9] = 0xFF;
    data[10] = 0xFF;
    data[11] = 0x00;
    data[12] = 0x05;
    data[13] = 0x00;
    data[14] = 0x00;
    data[15] = 0x01;
    data[16] = 0xAA;
    data[17] = 0xcc;
    data[18] = 0xcc;

    while (1)
    {
        // memset(data, i, TCP_TEST_SIZE);
        // fprintf(stdout, "client1SendFunc\n");
        svUv->gTcpClientSend(TEST_CLIENT2_IP, TEST_CLIENT2_PORT, data, 19);
        i++;
        delayMs(100);
        // sleep(1);
    }
}

static void client2RecvFunc(void *arg)
{
    class svuv *svUv = (class svuv *)arg;
    uint8_t *buff = new uint8_t [128 * 1024];
    int32_t ret = 0;
    int32_t allLen = 0;
    unsigned long long now = 0;

    while (1)
    {
        memset(buff, 0x00, 128 * 1024);

        ret = svUv->gTcpClientRecv(TEST_CLIENT2_IP, TEST_CLIENT2_PORT, buff, 128 * 1024);
        if (ret > 0)
        {
            allLen += ret;
            // if (allLen >= TCP_TEST_SIZE)
            {
                fprintf(stdout, "client2RecvFunc\n");
                fprintf(stdout, "recv %d , data %02x %02x\n", ret, buff[0], buff[1]);
                allLen = 0;
            }
        }
        // sysGetCurPts(&now);
        // printf("usleep time = %lld\n", now);

        // usleep(1000);
        delayMs(1);
    }
}

/*******************************************************TCP Server***************************************************************************************/
static void server1RecvFunc(void *arg)
{
    class svuv *svUv = (class svuv *)arg;
    uint8_t *buff = new uint8_t [128 * 1024];
    int32_t ret = 0;
    int32_t allLen = 0;
    static int fd = -1;

    unsigned long long start = 0;
    unsigned long long end = 0;
    uint32_t count = 0;

    if (fd < 0)
        fd = open("/data/app/recv_data.bin", O_CREAT | O_APPEND | O_TRUNC | O_RDWR, 0666);

    while (1)
    {
        memset(buff, 0x00, 128 * 1024);
        ret = 0;

        ret = svUv->gTcpServerRecv(TEST_CLIENT1_IP, TEST_CLIENT1_PORT, buff, 128 * 1024);
        if (ret > 0)
        {
            allLen += ret;
            // if (allLen >= TCP_TEST_SIZE)
            {
                fprintf(stdout, "server1RecvFunc\n");
                fprintf(stdout, "recv %d , data %02x %02x\n", ret, buff[0], buff[1]);
                allLen = 0;

                if (fd > 0)
                {
                    write(fd, buff, ret);
                }

                count++;
                if (count == 1)
                {
                    sysGetCurPts(&start);
                }

                if (count == 5549)
                {
                    sysGetCurPts(&end);
                    printf("recv time = %lld us\n", end - start);
                }
            }
        }

        delayMs(1);
        // usleep(100);
    }
}

static void server1SendFunc(void *arg)
{
    class svuv *svUv = (class svuv *)arg;
    uint8_t *data = new uint8_t [TCP_TEST_SIZE];
    uint8_t i = 0;
    int32_t remainSpace = 0;

    data[0] = 0xD2;
    data[1] = 0x8C;
    data[2] = 0x02;
    data[3] = 0x00;
    data[4] = 0xFF;
    data[5] = 0xFF;
    data[6] = 0xFF;
    data[7] = 0xFF;
    data[8] = 0xFF;
    data[9] = 0xFF;
    data[10] = 0xFF;
    data[11] = 0x00;
    data[12] = 0x05;
    data[13] = 0x00;
    data[14] = 0x00;
    data[15] = 0x01;
    data[16] = 0xAA;
    data[17] = 0xbb;
    data[18] = 0xcc;

    while (1)
    {
        svUv->gTcpServerSend(TEST_CLIENT1_IP, TEST_CLIENT1_PORT, data, 19);
        i++;
        // remainSpace = svUv->gTcpServerGetRemainSpace(TEST_CLIENT1_IP, TEST_CLIENT1_PORT);
        // printf("remainSpace = %d\n", remainSpace);
        delayMs(100);
    }
}

static void server2RecvFunc(void *arg)
{
    class svuv *svUv = (class svuv *)arg;
    uint8_t *buff = new uint8_t [128 * 1024];
    int32_t ret = 0;
    int32_t allLen = 0;

    while (1)
    {
        memset(buff, 0x00, 128 * 1024);

        ret = svUv->gTcpServerRecv(TEST_CLIENT2_IP, TEST_CLIENT2_PORT, buff, 128 * 1024);
        if (ret > 0)
        {
            allLen += ret;
            // if (allLen >= TCP_TEST_SIZE)
            {
                fprintf(stdout, "server2RecvFunc\n");
                fprintf(stdout, "recv %d , data %02x %02x\n", ret, buff[0], buff[1]);
                allLen = 0;
            }
        }

        delayMs(1);
    }
}

static void server2SendFunc(void *arg)
{
    class svuv *svUv = (class svuv *)arg;
    uint8_t *data = new uint8_t [TCP_TEST_SIZE];
    uint8_t i = 0;
    int32_t remainSpace = 0;

    data[0] = 0x4D;
    data[1] = 0x73;
    data[2] = 0x02;
    data[3] = 0x00;
    data[4] = 0xFF;
    data[5] = 0xFF;
    data[6] = 0xFF;
    data[7] = 0xFF;
    data[8] = 0xFF;
    data[9] = 0xFF;
    data[10] = 0xFF;
    data[11] = 0x00;
    data[12] = 0x05;
    data[13] = 0x00;
    data[14] = 0x00;
    data[15] = 0x01;
    data[16] = 0xAA;
    data[17] = 0xbb;
    data[18] = 0xcc;

    while (1)
    {
        svUv->gTcpServerSend(TEST_CLIENT2_IP, TEST_CLIENT2_PORT, data, 19);
        i++;
        // remainSpace = svUv->gTcpServerGetRemainSpace(TEST_CLIENT1_IP, TEST_CLIENT1_PORT);
        // printf("remainSpace = %d\n", remainSpace);
        delayMs(100);
    }
}

int main(int argc, char *argv[])
{
    printf("hello\n");

    class svuv *svUv = new svuv();

    if (argv[1][0] == 'C')
    {
        printf("client***\n");
        svUv->gaddTcpClient(argv[2], TEST_SERVER_M1_PORT, TEST_CLIENT1_IP, TEST_CLIENT1_PORT);
        // svUv->gaddTcpClient(TEST_SERVER_M2_IP, TEST_SERVER_M2_PORT, TEST_CLIENT2_IP, TEST_CLIENT2_PORT);

        // uv_thread_t tc1SendDatathId;
        // uv_thread_create(&tc1SendDatathId, client1SendFunc, svUv);

        uv_thread_t tc1RecvDatathId;
        uv_thread_create(&tc1RecvDatathId, client1RecvFunc, svUv);

        // delayMs(1000);
        // uv_thread_t tc2SendDatathId;
        // uv_thread_create(&tc2SendDatathId, client2SendFunc, svUv);

        // uv_thread_t tc2RecvDatathId;
        // uv_thread_create(&tc2RecvDatathId, client2RecvFunc, svUv);

    }
    else if (argv[1][0] == 'S')
    {
        printf("server1\n");
        svUv->gaddTcpServer(argv[2], TEST_SERVER_M1_PORT);
        
        uv_thread_t ts1RecvDatathId;
        uv_thread_create(&ts1RecvDatathId, server1RecvFunc, svUv);

        // uv_thread_t ts1SendDatathId;
        // uv_thread_create(&ts1SendDatathId, server1SendFunc, svUv); 
    }
    else if (argv[1][0] == 'D')
    {
        printf("server2\n");
        svUv->gaddTcpServer(TEST_SERVER_M2_IP, TEST_SERVER_M2_PORT);

        uv_thread_t ts2RecvDatathId;
        uv_thread_create(&ts2RecvDatathId, server2RecvFunc, svUv);

        uv_thread_t ts2SendDatathId;
        uv_thread_create(&ts2SendDatathId, server2SendFunc, svUv); 
    }

    svUv->gStartLoop();

    return 0;
}

#elif (TEST_MODULE == TEST_SVFIFO)          // TEST_MODULE
int main(int argc, char *argv[])
{
    class svfifo *svFIFO = new class svfifo();
    int ret = 0;

    if (argv[1][0] == 'w')
    {
        printf("fifoName = %s\n", argv[2]);
        svFIFO->openWriteFIFO(argv[2]);

        while (1)
        {
            ret = svFIFO->writeFIFO(argv[2], (char *)"123456789", strlen("123456789") + 1);
            printf("writeFIFO ret = %d\n", ret);
            delayMs(1000);
        }
    }
    else if (argv[1][0] == 'r')
    {
        char buff[32];
        memset(buff, 0x00, sizeof(buff));
        
        svFIFO->openReadFIFO(argv[2]);

        while (1)
        {
            ret = svFIFO->readFIFO(argv[2], buff, sizeof(buff));
            if (ret > 0)
            {
                fprintf(stdout, "readFIFO: %s\n", buff);
                ret = 0;
            }

            delayMs(1000);
        }
        svFIFO->closeReadFIFO(argv[2]);
    }

    return 0;
}

#elif (TEST_MODULE == TEST_SVCP)
int main(int argc, char *argv[])
{
    int ret = 0;

    ret = svcp(argv[1], argv[2]);
    
    return ret;
}
#elif (TEST_MODULE == TEST_SVDEBUG)

#define TAG    "test"
int main (int argc , char *argv[])
{
    LOG_DBG(TAG, "log_debug %d \n", LOG_LEVEL_DEBUG);
    // LOG_INFO(TAG, "log_info %d \n", LOG_LEVEL_INFO);
    // LOG_WARN(TAG, "log_warn \n");
    // LOG_ERR(TAG, "log_err \n");

    return 0;
}

#endif
